문서의 임의 삭제는 제재 대상으로, 문서를 삭제하려면 삭제 토론을 진행해야 합니다. 문서 보기문서 삭제토론 스파게티 코드 (문단 편집) == 발생 원인 == 보통 계획없이 바로 코딩을 시작하거나 요구사항이 원래 기획한 범위를 크게 벗어날 때 혹은 [[프로그래머]]의 [[알고리즘]] 구현 실력이 지나치게 떨어질 때 주로 출현한다. 중간에 인원이 바뀌면서 전임자가 짜 놓은 코드 의 인수인계가 잘 되지 못하고 이해도가 떨어질 경우 발행하기 쉽다. 발적화도 덤으로 나타나는 경우가 많지만, 스파게티 소스 코드라고 모두 실제 작동에서 비효율적인 것은 아니다. * 함수/메소드가 둘 이상의 작업을 한다. 하나의 함수/메소드에서는 논리적으로 구분되는 가장 작은 단위의 작업을 처리하는 게 이상적이다. 이 규칙을 어겼을 때 로직이 꼬이면서 스파게티 코드가 발생한다. 하나의 함수/메소드의 코드의 길이가 1000줄이 넘는다면 거의 대부분 이런 경우다. 또 다른 기준으로, 로컬 변수의 특정한 그룹이 함수의 일부 영역에서만 변경되고 나머지 영역에서는 단지 읽기만 할 때 그 변수를 마지막으로 조작한 지점까지를 하나의 작업 단위로 정의하고 코드를 분리할 수도 있다. 이러한 면에서 혹자는 함수의 매개변수에 boolean[* 참, 거짓을 저장하는 변수]를 받으면 안 된다고 한다. * 논리적으로 하나의 작업 단위를 억지로 둘 이상의 함수/메소드로 쪼개는 경우 * 여러 함수/메소드들이 지나치게 서로서로 의존하면서 얽혀있는것. 특히 전혀 상관없는 클래스들의 메소드 (인터페이스도 아니고 상속한것도 아닌...)들이 뒤죽박죽 얽혀있으면 그냥 답이 없다. 이럴 경우 메소드 하나를 조금 손 보면 프로그램 전체가 오작동하기 십상이기 때문에 디버깅은 물론이고 기능 확장 같은게 악몽이된다. 귀찮아서 다시 짜지 않고 계속 방치할 경우 언제 터질지 모르는 시한 폭탄이 된다. 거대한 메소드의 가독성을 높이기 위해서 특정 부분들을 작은 메소드들로 쪼개서 코딩하는건 좋지만 너무 마구 엉키지 않게 조심해야 한다. * if-else 문의 계층이 지나치게 얽혀 있다. 여러 조건을 동시에 비교하는 경우에는 '''진리표'''나 '''패턴 매칭'''을 대신 사용해야 한다. [[순서도]]를 그렸을 때 마름모(조건분기 기호)가 나무뿌리처럼 얽혀 있는 코드는 훌륭한 스파게티 코드다. 개별 변수 a, b, c 를 if-else 로 하나씩 비교하는 대신 if a and (not b) and c then 'do something' 하는 식으로 모든 조건을 '''한꺼번에''' 검사하면서 내려가라는 얘기다. 혹은 별도의 '평가 함수'를 작성하는 방법도 있다. if(eval_function(a,b,c, goal) == true) then 'do someting' 하는 식이다. [[C++]]에서 진리표를 구현하는 방식은 여러 가지인데 그 중에서 비트 마스크 방식의 진리표는 다음과 같다. int 사용시 32개의 조건을, long 사용시 최대 64개의 TRUE/FALSE 조건을 고속으로 검사할 수 있다. {{{#!syntax cpp #include #include int main(void) { bool a = true; bool b = false; bool c = true; int condition = ((int)a << 2) | ((int)b << 1) | ((int)c); printf("%d\n", condition); // 4+1 = 5 if(condition == 0x0005) { printf("[a, b, c] == [T ,F, T]\n"); } } }}} * [[콜백 함수]] 콜백 계층이 지나치게 들어가 코드가 대각선으로 쓰여지는 경우 문제가 된다. 보통 3~5단계를 초과하는 콜백 체인은 스파게티 코드로 간주할 수 있다. 콜백 많기로 둘째가라면 서러울 [[Node.js]]가 가장 대표적인 예시. 아예 node.js의 단점을 [[http://callbackhell.com/|콜백 지옥]]이라고 표현할 정도.[* 오죽하면 아래 예제 코드의 움푹 들어간 부분에 [[파동권]]을 [[https://camo.githubusercontent.com/b77a13f5cbf54c35d3af0569f88eda9053e7a9ed716efe61e326291d0426e3ce/687474703a2f2f692e696d6775722e636f6d2f42746a5a6564572e6a7067|합성한 밈]]이 돌아다닐 정도. 그래서 보통 Promise나 async/await를 사용하여 해결한다.] 콜백 함수 문서 참조. {{{#!syntax javascript fs.readdir(source, function(err, files) { if (err) { console.log('Error finding files: ' + err) } else { files.forEach(function(filename, fileIndex) { console.log(filename) gm(source + filename).size(function(err, values) { if (err) { console.log('Error identifying file size: ' + err) } else { console.log(filename + ' : ' + values) aspect = (values.width / values.height) widths.forEach(function(width, widthIndex) { height = Math.round(width / aspect) console.log('resizing ' + filename + 'to ' + height + 'x' + height) this.resize(width, height).write(destination + 'w' + width + '_' + filename, function(err) { if (err) console.log('Error writing file: ' + err) }) }.bind(this)) } }) }) } }); }}} * 다중 for 루프 [[행렬]]을 처리할 때에는 다중 for루프가 하나의 논리적 처리 단위이므로 다중 for루프 자체는 스파게티 코드가 아니다. 문제는 [[트리(그래프)|트리 자료구조]] 등을 순회할 때 다중 for루프를 통해 처리하는 경우다. 트리 [[자료구조]](대표적으로 [[XML]]/[[JSON]])를 처리할 때에는 과감히 [[재귀함수]]를 사용해 줄 필요가 있다. 특히 다중 for 루프에서 break와 continue를 마구 남발하면 [[GOTO]]문을 사용한 것보다 코드의 흐름을 추적하기 더욱 더 어려워진다[* 몇 안되는 GOTO문 적절한 사용 예시가 다중 for 루프 탈출이다.]. [[재귀함수]]가 스택 깊이를 뚫을 수 있다거나 함수 호출 오버헤드가 있어서 쓸 수 없는 경우가 있어서 다중 for문을 사용해야 하는 경우도 있으나 이런 경우는 흔한 경우는 아니다. * [[포인터]] 남용 [[포인터]]는 양날의 검과 같다. 분명 강력하고 유용한 도구이지만 잘못 사용하면 그야말로 재앙이 된다. 값 복사의 오버헤드가 도저히 용납이 안 될 정도로 성능하락을 보이는 게 아니면 포인터 전달보다는 값 복사를 사용하는 편이 좋고, 그게 어려울 때에도 포인터를 '상수'로 간주해 한 번 할당한 값을 변경하지 않는 게 좋고, 그것도 여의치 않으면 최소한 포인터를 조작하는 로직을 코드의 한 군데에 모두 몰아넣어야 한다. * [[GOTO]] 남용 항목 참조. * 잘못된 [[프로그램 최적화]] 방법 남용 쓸데없는 루프 언롤링, 과도한 인트린식 사용, 매크로 남용 등이다. [[컴파일러]]의 최적화 엔진을 불신하는 '''꼰대''' 프로그래머들의 경향이기도 한데 이들이 만든 스파게티 코드는 컴파일러조차 해석에 애를 먹어서 최적화 엔진이 최적화를 포기하기 때문에 저성능, 불안정, 낮은 보안성을 모두 갖춘 쓰레기가 만들어진다. * 용도에 맞지 않는 [[프로그래밍 언어]]의 사용 그래픽 프로세싱용 언어로 데이터베이스 로직을 구현하거나 논리 프로그래밍 언어로 기계제어를 시도하는 경우 등. 원래 프로그래밍 언어가 상정한 활용 영역을 벗어나서 코딩하려니 라이브러리 지원도, 문법 지원도 받지 못하고 차라리 [[어셈블리어]]가 읽기 쉬워질 지경의 코드를 만들게 된다. 차라리 [[C++]]이나 [[Python]] 같은 건 범용 언어니 그렇다 치더라도, [[PHP]]로 인공지능 로직을 구현하려고 시도하는 건 도대체...[* 물론 PHP가 7.x로 올라가서 속도가 어마무시하게 빨라졌기에 [[https://github.com/php-ai|불가능한 건 아니다]].] * [[코딩 스타일]]이 통일되지 못함 특히 다소 마이너한 주제의 무보수 오픈소스 프로젝트에서 흔히 일어날 수 있는 일이다. 주제의 매니악함과 보수가 없음으로 인해 유입이 적고 엄격한 기여 규칙을 적용하기 어려워지기 때문이다. 또한 개발기간이 오래된 경우 과거의 잔재들이 남아있을 수 있는데, 이 경우 과거의 잔재가 버그의 온상이 된다. 특히 어느정도 [[C언어]] 스타일로 코딩할 수 있는 [[C++]]이 이런 경우가 많다. * [[매크로]] 남용저장 버튼을 클릭하면 당신이 기여한 내용을 CC-BY-NC-SA 2.0 KR으로 배포하고,기여한 문서에 대한 하이퍼링크나 URL을 이용하여 저작자 표시를 하는 것으로 충분하다는 데 동의하는 것입니다.이 동의는 철회할 수 없습니다.캡챠저장미리보기